:- module(matching_access, 
	[build_query/5,
	 make_query/4,
	 expand_solution/4,
	 query_add_search_terms/3,
	 query_remove_search_terms/3,
	 query_add_include_packages/3,
	 query_remove_include_packages/3,
	 query_add_exclude_packages/3,
	 query_remove_exclude_packages/3,
%% Types
         heuristic/1,
         solution/1,
         query/1,
         results/1
	], [assertions,basicmodes,regtypes,argnames]).

:- use_module('../DataBase/dictionary_access').

:- comment(title, "Top-Level matching engine interface").
:- comment(subtitle, "AMOS Project").

:- comment(author, "Jose Manuel Gomez, Manuel Carro, and the CLIP Group").
:- comment(author, "Facultad de Inform@'{a}tica").
:- comment(author, "Universidad Polit@'{e}cnica de Madrid").
:- comment(author, "@tt{clip@@dia.fi.upm.es}").
:- comment(author, "@tt{http://www.clip.dia.fi.upm.es/}").

:- comment(module, "

This module provides an interface for building and posting search
queries to a database containing descriptions of open source code
packages.  The interface operations are primarily aimed at creating a
bridge between a @bf{WWW interface} (or, in general, any end user) and
the @bf{ontology} implementation, offering a series of primitives to
connect both ends.

@bf{Building} means constructing a term which states which
capabilities are of interest (or of no interest).  Heuristics to be
used in order to direct the search towards a more promising answer
without exploring the whole of the search space can be stated.
Additionally, operations are provided to manage the query as an opaque
data structure, in order, e.g., to add / remove search terms from it.

@bf{Posting} the query refers to actually sending it to the matching
engine.  Each query posted specifies the number of solutions required
(useful to generate web pages) and it returns a @bf{new query}
expressing the state of the search after the last solution was found.
Posting this new query again will restart the search where it was left
before.

@sp

@include{../DataBase/three_argument_explanation.lpdoc}

@sp

@include{../Doc/acknowledgements.lpdoc}

@newpage

").

:- argnames is_a_query(
	terms,
	heuristic,
	includepack,
	excludepack) .

:- regtype query(?Query) # "@var{Query} is a query.".

query(Query):- functor(Query, is_a_query, 4).


:- regtype results(?Results) # "@var{Results} is a list of solutions.".

results(Results) :- list(Results, solution).


:- regtype solution(?Sol) # "@var{Sol} is a solution".

solution(Sol) :- list(Sol, atm).


:- regtype heuristic(?H) 

# "@var{H} is a valid heuristic, implemented as a ground term.  Valid
heuristics are:

@includedef{heuristic/1}".

heuristic(all).
heuristic(first(N)):- int(N).


:- pred build_query(?Terms, ?Heuristic, ?IncludePacks, ?ExcludePacks, ?Query):
	list(search_term) * atm * list(atm) * list(atm) * query

# "@var{Terms} is a a list of dictionary terms to be searched for,
describing the desired capabilities.  @var{Heuristic} is the heuristic
to follow during the search. @var{IncludePacks} is a list of packages
which have been selected by the user as interesting or advantageous
and which @bf{must} be included in the final solution.
@var{ExcludePacks} are packages which are not desired in a final
solution, and @var{Query} is a query including the all these terms and
which will be used to perform the search." .

build_query(_Terms, _Heuristic, _IncludePacks, _ExcludePacks, _Query) .



:- pred make_query(+Query, +MaxSols, ?Results, ?NextQuery) :
	query * int * list(result) * query

# "@var{Query} is the query that currently guides the search,
@var{Results} is a list of at most @var{MaxSols} solutions, and
@var{NextQuery} reflects where the current search has stopped so that
@pred{make_query/4} can restart it at that point. If @var{Results} is
an empty list, then no solutions have been found (and further calls to
@pred{make_query/4} with @var{NextQuery} will not yield any more
solutions).".

make_query(_Query, _MaxSols, _Results, _NextQuery) .



:- pred expand_solution(+Solution, ?Packages, ?Fulfilled, ?Flooded) :
	solution * list(atm) * list(search_term) * list(search_term)

# "@pred{expand_solution/4} receives a solution @var{Solution} and
gathers more information about the results of the search which lead to
that solution:

@begin{itemize}

@item The list of package names returned (@var{Packages})

@item which capabilities (either initially requested or internally
required by the search process) were found (@var{Fulfilled}), and

@item which capabilities were needed, but were not satisfied
(@var{Flooded}).  @end{itemize}".

expand_solution(_Solution, _Packages, _Fulfilled, _Flooded) .



:- pred query_add_search_terms(+Query, +Terms, ?NewQuery) :
	query * list(search_term) * query

# "@pred{query_add_search_terms/3} changes query @var{Query} to query
@var{NewQuery} by adding new search terms @var{Terms} into it.".

query_add_search_terms(_Query, _Terms, _NewQuery) .



:- pred query_remove_search_terms(+Query, +Terms, ?NewQuery) :
	query * list(search_term) * query

# "@pred{query_remove_search_terms/3} changes query @var{Query} to
query @var{NewQuery} by removing the search terms @var{Terms} from
it.".

query_remove_search_terms(_Query, _Terms, _NewQuery) .



:- pred query_add_include_packages(+Query, +Packages, ?NewQuery) :
	query * list(atm) * query

# "@pred{query_add_include_packages/3} changes query @var{Query} to
query @var{NewQuery} by adding new packages @var{Packages} to appear
in a final solution.".


query_add_include_packages(_Query, _Terms, _NewQuery) .



:- pred query_remove_include_packages(+Query, +Packages, ?NewQuery) :
	query * list(atm) * query

# "@pred{query_remove_include_packages/3} changes query @var{Query} to
query @var{NewQuery} by removing @var{Packages} from the list of
packages to appear in a final solution.".

query_remove_include_packages(_Query, _Terms, _NewQuery) .


:- pred query_add_exclude_packages(+Query, +Packages, ?NewQuery) :
	query * list(atm) * query

# "@pred{query_add_exclude_packages/3} transforms the query
@var{Query} into the query @var{NewQuery} by adding the list of
packages @var{Packages} to those which will be excluded from the final
solution.".

query_add_exclude_packages(_Query, _Terms, _NewQuery) .


:- pred query_remove_exclude_packages(+Query, +Packages, ?NewQuery) :
	query * list(atm) * query

# "@pred{query_remove_exclude_packages/3} transforms the query
@var{Query} into the query @var{NewQuery} by removing the list of
packages @var{Packages} from those to be excluded from the final
solution.".

query_remove_exclude_packages(_Query, _Terms, _NewQuery) .
